package src.application.Doppelkopf;

import java.io.*;
import java.net.Socket;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Klasse, um den Client zu realisieren
 *
 * @author b.osterholt
 *
 */
public class Client {

    private String username, ip, server;
    private int port = 0, nr=-1; //Nr = der wie vielte Spieler ist der Client
    private boolean change = true, empfange = false, connected = false;
    private String namen[] = new String[4];
    private Socket socket = null;
    private Spieler spieler;
    private SpielFrame spielF;
    private WarteFrame warteF;
    private DataOutputStream outstream;
    private DataInputStream instream;
    private ClientConnection readConnection;
    protected HashMap<Integer, String> userlist;
    private static boolean login, warte;
//bei Programmbeenden müssen noch socket, in, out, ... geschlossen werden    

    public void setLogin(boolean b){
        login=b;
    }
    
    public Spieler getSpieler() {
        return spieler;
    }

    public int getNummer() {
        return nr;
    }
    
    public void setIp(String aIp) {
        if (change) {
            ip = aIp;
        }
    }

    public void setPort(int aPort) {
        if (change) {
            port = aPort;
        }
    }

    public void setUsername(String aUsername) {
        if (change) {
            username = aUsername;
            spieler.setName(username);
        }
    }

    public void setFrames(SpielFrame spiel, WarteFrame warteF) {
        spielF = spiel;
        this.warteF = warteF;
    }

    public Client() {
        spieler = new HSpieler();
        login = true;   //logInFrame darf geoeffnNormales Spielet werden, wenn login=true
        warte = false;  //warteFrame darf nicht geoeffnet werden, wenn warte=false
    }
    
    /**
     * verbindet den Client mit dem Socket server.
     * empfaengt erste Nachrichten vom Server
     */
    public void verbinde() {
        change = false;   //Keine Änderungen bei IP, Username, Port mehr möglich
        byte[] b = new byte[100];
        ByteArrayOutputStream bout = new ByteArrayOutputStream();

        try {
            //mit dem Socket verbinden; In- und Outputstreams speichern
            socket = new Socket(ip, port);	//6564 ist Port
            outstream = new DataOutputStream(socket.getOutputStream());
            instream = new DataInputStream(socket.getInputStream());
            
            outstream.write(username.getBytes()); //Username senden
            //Begruessung & Spielernummer empfangen
            if ((instream.read(b)) != -1) {
                bout.write(b);  //bytearray dauf bytearrayoutputstream schreiben
                String[] split = bout.toString().split("#"); 
                System.out.println(split[0]);    //Begruessung ausgeben
                nr = Integer.parseInt(split[2]); //Spielernummer speichern
                System.out.println("Bin Da");

            }
        }
        catch (NumberFormatException e) {
            System.out.println("NumberFormat Fehler  " + e.getMessage());
            e.printStackTrace();
        }
        catch (IOException e) {
            System.out.println("IO Fehler    " + e.getMessage());
            e.printStackTrace();
        }
        catch (Exception e) {
            System.out.println("Verbindungsfehler  " + e.getMessage());
            e.printStackTrace();
            System.exit(1);
        }//ende Try-catch

        empfange = true;
    }
    
    /**
     * sendet den uebergebenen String an den Server
     * @param s : zu sendender String
     */
    public void sende(String s) {
        try {
            if (s.charAt(0) == 'H') {//gespielte Karte wurde gesendet -> Zug vorbei
                spielF.aktiv(false);
            }
            System.out.println("Sende ETWAS +++" + s);
            
            outstream.write((s + "$END$").getBytes());
        }catch (IOException e) { System.out.println("Recieve :" + e.getMessage()); }
    }

    /**
     * empfaengt vom Server einen String
     * @return : -1 falls nicht erfolgreich; 0: Spiel beginnt; 1: Handkarte spielen;
     *            2: Karte wurde gespielt; 3: Ansage/Vorbehalt wurde gemacht
     */
    public int empfange() {
        byte[] b = new byte[100];
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        String input;
        int rtn;

        try {
            System.out.println("EMPFANGE - MAIN" + empfange);
            bout.flush();
            if (empfange) {
                while ((instream.read(b) == - 1)) {} //warten bis EINMAL was empfangen wurde
                //hat was empfangen
                bout.write(b);  //bytearray auf bytearrayoutputstream schreiben
                input = bout.toString();
                System.out.println("EMPFANGE ETWAS +++" + input);
                
                //überprüft durch zweite Methode empfange(String), was gesendet wurde und gibt den fall zurück
                if ((rtn = empfange(input)) >= 0) {
                    return rtn;
                }
            }
            //EOFException, wenn der Server zuerst beendet wird.
        }
        catch (IOException e1) {
            System.out.println("Recieve IO:" + e1.getMessage());
            e1.printStackTrace();
        }
        catch (Exception e) {
            System.out.println("Recieve Exc:" + e.getMessage());
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * hat vom Server einen String empfangen und ueberprueft diesen
     * @param input: String, der empfangen wurde
     * @return : -1 falls nicht erfolgreich; 0: Spiel beginnt; 1: Handkarte spielen;
     *            2: Karte wurde gespielt; 3: Ansage/Vorbehalt wurde gemacht
     */
    public int empfange(String input) {
        String[] split = input.split("#");
        switch (split[0]) {
            case "B":
            //B -> Beginn + Handkarten jedes Spielers + Namen aller Spieler in der Reihenfolge ab mir
                spielF.setVisible(true);
                warteF.setVisible(false);
                int j = 1;
                for (int i = 0; i < 10; i++) {    //Handkarten speichern
                    spieler.handkarten[i] = new Karte(Integer.parseInt(split[j + 1]), split[j].charAt(0));
                    spieler.handkarten[i].setSpielart(1);
                    j = j + 2;
                }
                //setze Namen der Spieler                
                spielF.setNamen(split[j], split[j + 1], split[j + 2], split[j + 3]);
                spielF.kartenAnzeigen();
                for (int i=0; i<4; i++)
                    namen[i] = split[j+i];
                spielF.starteRunde();
                spielF.aktiv(false);
                warte=false;
                return 0;
                
            case "H":
                //karten duerfen angeklickt werden & wurde eine karte angeklickt, muss sie zurueckgegeben werden
                spielF.aktiv(true);
                System.out.println("Bitte Karte anklicken und so auswählen!");
                spielF.zeigeGueltigeKarten();
                //Frame sendet dann die Karte
                return 1;
                
            case "S": //String der Form: "#S#"+nr+"#"+wert+"#"+farbe+"#"
                //hinmalen, was gelegt wurde
                Karte card = new Karte(Integer.parseInt(split[3]), split[2].charAt(0));
                int nrKarte = Integer.parseInt(split[1]); // Spieler, der Karte gespielt hat
                int pos;
                pos = (4 + nrKarte - nr)%4;
                this.spieler.stich[pos] = card;
                spielF.kartenEntfernen(pos);
                spielF.zeigeStich();
                return 2;
                
            case "V": // "V#1.vorbehalt#spieler#2.vorbehalt#spieler#$END$
                String spielart = split[1];
                int sp2, sp1 = (4+Integer.parseInt(split[2]) - nr)%4;
                System.out.println(spielart);
                if (split.length > 4) {//Hochzeit + Schweinchen
                    for (int i=0; i<10; i++)
                            spieler.handkarten[0].setSpielart(6);
                    sp2 = Integer.parseInt(split[4]);
                    switch(spielart){
                        case "H1#": 
                            spielF.schreibeNachricht("Hochzeit, erster Fremder: " + namen[sp1]+"Schweinchen: " + namen[sp2]);
                            break;
                        case "H2#":
                            spielF.schreibeNachricht("Hochzeit, erster Fremder Fehl: " + namen[sp1]+"Schweinchen: " + namen[sp2]);
                            break;
                        case "H3#":
                            spielF.schreibeNachricht("Hochzeit, erster Fremder Trumpf: " + namen[sp1]+"Schweinchen: " + namen[sp2]);
                            break;
                        case "H4#": 
                            spielF.schreibeNachricht("Hochzeit, zweiter Fremder: " + namen[sp1]+"Schweinchen: " + namen[sp2]);
                            break;
                    }    
                }
                else{
                    switch(spielart){
                        case "N": // Normalspiel
                            for (int i=0; i<10; i++)
                                spieler.handkarten[i].setSpielart(0);
                            spielF.schreibeNachricht("Normales Spiel");
                            break;
                        case "S": //Schweinchen
                            for (int i=0; i<10; i++)
                                spieler.handkarten[i].setSpielart(4);
                            spielF.schreibeNachricht("Schweinchen: " + namen[sp1]);
                            break;
                        case "D": 
                            for (int i=0; i<10; i++)
                                spieler.handkarten[i].setSpielart(2);
                            spielF.schreibeNachricht("Damensolo: " + namen[sp1]);
                            spielF.setPartei(true, sp1);
                            break;
                        case "B": 
                            for (int i=0; i<10; i++)
                                spieler.handkarten[i].setSpielart(1);
                            spielF.schreibeNachricht("Bubensolo: " + namen[sp1]);
                            spielF.setPartei(true, sp1);
                            break;
                        case "F": 
                            for (int i=0; i<10; i++)
                                spieler.handkarten[i].setSpielart(3);
                            spielF.schreibeNachricht("Fleischlos: " + namen[sp1]);
                            break;
                        case "H1#": 
                            for (int i=0; i<10; i++)
                                spieler.handkarten[i].setSpielart(5);
                            spielF.schreibeNachricht("Hochzeit, erster Fremder: " + namen[sp1]);
                            break;
                        case "H2#":
                            for (int i=0; i<10; i++)
                                spieler.handkarten[i].setSpielart(5);
                            spielF.schreibeNachricht("Hochzeit, erster Fremder Fehl: " + namen[sp1]);
                            break;
                        case "H3#":
                            for (int i=0; i<10; i++)
                                spieler.handkarten[i].setSpielart(5);
                            spielF.schreibeNachricht("Hochzeit, erster Fremder Trumpf: " + namen[sp1]);
                            break;
                        case "H4#": 
                            for (int i=0; i<10; i++)
                                spieler.handkarten[i].setSpielart(5);
                            spielF.schreibeNachricht("Hochzeit, zweiter Fremder: " + namen[sp1]);
                            break;
                    }
                }
                //Handkarten wieder sortieren und deu ausgeben
                java.util.Arrays.sort(spieler.handkarten);
                spielF.kartenAnzeigen();
                return 5;
                
            case "A":                
                System.out.println("Anfang");
                String s = split[1] + " sagt: ";
                switch (split[2]){
                    case "R": s += "Re"; break;
                    case "C": s += "Contra"; break;
                }
                switch (split[3]){
                    case "9": s += " keine 90"; break;
                    case "6": s += " keine 60"; break;
                    case "3": s += " keine 30"; break;
                    case "0": s += " Schwarz"; break;    
                }
                System.out.println(s);
                spielF.schreibeNachricht(s);
                System.out.println("Ende");
                return 3;
            case "G":
                spielF.schreibeNachricht("Stichgewinner: " + split[1]);
                
                try {Thread.sleep(500);     //Stich kurz liegen lassen
                } catch (InterruptedException ex) {
                  Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                }
                spielF.stichLeeren();
                System.out.println("Stich leer");
                return 4;
            case "R":
                System.out.println(input);
                spielF.schreibeNachricht(input.split("#")[1].split("//$")[0]);
                return 5;
            default:
                return -1;
        }
    }

    /**
     * Main
     * @param argu 
     */
    public static void main(String[] argu) {
        Client cl = new Client();
        LogInFrame loginF = new LogInFrame(cl);
        loginF.setVisible(true);
        SpielFrame spielF = new SpielFrame(cl);
        spielF.setVisible(false);
        WarteFrame warteF = new WarteFrame();
        warteF.setVisible(false);
        cl.setFrames(spielF, warteF);

        while (login) {
            try {Thread.sleep(50);
                } catch (InterruptedException ex) {
                  Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                }
            // Login laeuft
        }
        warte=true;
        cl.verbinde();
        System.out.println("LogInFertig"); //anschl wird SpielFrame gestartet
        warteF.setVisible(true);

        while (warte) {
            cl.empfange();
        }

        System.out.println("Warten fertig"); //--> Spiel beginnt
        while (true) {
            cl.empfange();
        }
    }
}
       
/* SENDEN UND EMPFANGEN
           //Text empfangen
           int len; byte[] b = new byte[100]; String text="";
           ByteArrayOutputStream bout = new ByteArrayOutputStream();
           if ((len = in.read(b)) != -1) {
                    bout.write(b);  //bytearray auf bytearrayoutputstream schreiben
                    text = bout.toString();
                    System.out.println(text);
		}
    (text+"$END$")
             
            //schreiben
            out.write(("striiiiing").getBytes());
*/
